<template>
  <view
    class="gui-sbody gui-flex gui-column"
    :class="[fullPage || refresh || loadmore ? 'gui-flex1' : '']"
    :style="{ opacity: pageStatus ? 1 : 0 }"
  >
    <!-- 自定义头部 -->
    <view v-if="customHeader" id="guiPageHeader" ref="guiPageHeader" class="gui-header gui-transition-all" :class="headerClass">
      <!-- 状态栏 -->
      <view class="gui-page-status-bar" :class="statusBarClass" :style="{ height: statusBarHeight + 'px' }">
        <slot name="gStatusBar"></slot>
      </view>
      <!-- 头部插槽 -->
      <view class="gui-flex gui-column gui-justify-content-center" @tap.stop.prevnet="headerTap">
        <slot name="gHeader"></slot>
      </view>
    </view>
    <!-- 自定义头部占位 -->
    <view v-if="customHeader && isHeaderSized" :style="{ height: headerHeight + 'px' }" />

    <!-- 页面主体 -->
    <view
      v-if="!refresh && !loadmore"
      id="guiPageBody"
      ref="guiPageBody"
      class="gui-flex gui-column gui-relative"
      :class="[fullPage ? 'gui-flex1' : '']"
    >
      <slot name="gBody"></slot>
    </view>

    <!-- 刷新加载主体  非 nvue -->
    <!-- #ifndef APP-NVUE -->
    <view
      v-if="refresh || loadmore"
      id="guiPageBody"
      ref="guiPageBody"
      class="gui-flex1 gui-relative"
      :style="{ marginTop: fixedTopMargin + 'px' }"
    >
      <scroll-view
        class="gui-absolute-full"
        :scroll-into-view="topTagID"
        :scroll-y="true"
        :scroll-with-animation="false"
        :show-scrollbar="false"
        @scroll="scroll"
        @scrolltolower="loadmorefun"
        @touchend="touchend"
        @touchmove="touchmove"
        @touchstart="touchstart"
      >
        <view id="guiPageBodyTopTag">
          <gui-refresh
            ref="guiPageRefresh"
            :custom-class="refreshClasses"
            :refresh-font-size="refreshFontSize"
            :refresh-text="refreshText"
            :trigger-height="reFreshTriggerHeight"
            @reload="reload"
          />
        </view>
        <slot name="gBody"></slot>
        <view v-if="loadmore">
          <gui-loadmore
            ref="guipageloadmore"
            :custom-class="loadMoreClass"
            :load-more-font-size="loadMoreFontSize"
            :load-more-text="loadMoreText"
            :status="loadMoreStatus"
          />
        </view>
      </scroll-view>
    </view>
    <!-- #endif -->

    <!-- 刷新加载主体 nvue -->
    <!-- #ifdef APP-NVUE -->
    <view
      v-if="refresh || loadmore"
      id="guiPageBody"
      ref="guiPageBody"
      class="gui-flex gui-column gui-flex1"
      :style="{ marginTop: fixedTopMargin + 'px' }"
    >
      <list class="gui-flex1" :show-scrollbar="false" @loadmore="loadmorefun" @scroll="scroll">
        <refresh v-if="refresh" :display="refreshing ? 'show' : 'hide'" @pullingdown="onpullingdown" @refresh="onrefresh" />
        <cell ref="guiPageBodyTopRef" />
        <cell v-if="refresh">
          <gui-refresh
            ref="guiPageRefresh"
            :custom-class="refreshClasses"
            :refresh-font-size="refreshFontSize"
            :refresh-text="refreshText"
            :trigger-height="reFreshTriggerHeight"
          />
        </cell>
        <slot name="gBody"></slot>
        <cell v-if="loadmore" class="gui-page-loadmore">
          <gui-loadmore
            ref="guipageloadmore"
            :custom-class="loadMoreClass"
            :load-more-font-size="loadMoreFontSize"
            :load-more-text="loadMoreText"
            :status="loadMoreStatus"
          />
        </cell>
      </list>
    </view>
    <!-- #endif -->

    <!-- 页面底部 -->
    <!-- 底部占位 -->
    <view v-if="customFooter" :style="{ height: footerHeight + 'px' }" />
    <view v-if="customFooter" id="guiPageFooter" ref="guiPageFooter" class="gui-page-footer gui-border-box" :class="footerClass">
      <slot name="gFooter"></slot>
      <gui-iphone-bottom :custom-class="footerSpaceClass" :need="!isSwitchPage" />
    </view>

    <!-- 右下角悬浮挂件 -->
    <view class="gui-page-pendant" :class="pendantClass">
      <slot name="gPendant"></slot>
    </view>

    <!-- 吸顶元素 -->
    <view id="guiPageFixedTop" ref="guiPageFixedTop" class="gui-page-fixed-top" :style="{ top: fixedTop + 'px' }">
      <slot name="gFixedTop"></slot>
    </view>

    <!-- 全屏 loading -->
    <gui-page-loading ref="guipageloading" />
  </view>
</template>
<script>
// #ifdef APP-NVUE
const dom = weex.requireModule('dom')
// #endif
export default {
  name: 'GuiPage',
  props: {
    // #ifndef APP-NVUE
    fullPage: { type: Boolean, default: false },
    // #endif
    // #ifdef APP-NVUE
    fullPage: { type: Boolean, default: true },
    // #endif

    // 自定义头部
    customHeader: { type: Boolean, default: false },
    headerClass: {
      type: Array,
      default: function () {
        return []
      },
    },
    isHeaderSized: { type: Boolean, default: true },
    statusBarClass: {
      type: Array,
      default: function () {
        return ['gui-bg-white']
      },
    },

    // 自定义底部
    customFooter: { type: Boolean, default: false },
    footerClass: {
      type: Array,
      default: function () {
        return []
      },
    },
    footerSpaceClass: {
      type: Array,
      default: function () {
        return ['gui-bg-gray', 'gui-dark-bg-level-2']
      },
    },
    customFooterHeight: { type: Number, default: 100 },

    // 挂件
    pendantClass: {
      type: Array,
      default: function () {
        return []
      },
    },

    // 全屏加载状态
    isLoading: { type: Boolean, default: false },
    isSwitchPage: { type: Boolean, default: false },

    // 吸顶插槽样式
    fixedTopClass: {
      type: Array,
      default: function () {
        return []
      },
    },

    /* 刷新 */
    refresh: { type: Boolean, default: false },
    refreshText: {
      type: Array,
      default: function () {
        return ['继续下拉刷新', '松开手指开始刷新', '数据刷新中', '数据已刷新']
      },
    },
    refreshClasses: {
      type: Array,
      default: function () {
        return [['gui-color-gray'], ['gui-color-gray'], ['gui-primary-text'], ['gui-color-green']]
      },
    },
    refreshFontSize: { type: Number, default: 26 },

    /* 加载更多 */
    loadmore: { type: Boolean, default: false },
    loadMoreText: {
      type: Array,
      default: function () {
        return ['', '数据加载中', '已加载全部数据', '暂无数据']
      },
    },
    loadMoreClass: {
      type: Array,
      default: function () {
        return ['gui-color-gray']
      },
    },
    loadMoreFontSize: { type: String, default: '26rpx' },
    loadMoreStatus: { type: Number, default: 1 },
    apiLoadingStatus: { type: Boolean, default: false },
    reFreshTriggerHeight: { type: Number, default: 50 },
  },
  emits: ['scroll', 'reload', 'loadmorefun', 'gotoTop'],
  data() {
    return {
      pageStatus: false,
      footerHeight: 50,
      statusBarHeight: 44,
      // #ifndef H5
      headerHeight: 72,
      // #endif
      // #ifdef H5
      headerHeight: 44,
      // #endif
      headerTapNumber: 0,
      fixedTop: 0,
      loadMoreTimer: null,
      fixedTopMargin: 0,
      scrollTop: 0,
      srcollTimer: null,
      refreshing: false,
      pullingdownVal: 0,
      topTagID: 'no',
    }
  },
  watch: {
    isLoading: function (val) {
      if (val) {
        this.pageLoadingOpen()
      } else {
        this.pageLoadingClose()
      }
    },
  },
  mounted: function () {
    // 初始化底部高度
    if (this.customFooter) {
      this.footerHeight = uni.upx2px(this.customFooterHeight)
      // #ifdef MP-WEIXIN
      if (!this.isSwitchPage) {
        if (this.isIphoneBottom()) {
          this.footerHeight += uni.upx2px(60)
        }
      }
      // #endif
    }

    // 全屏 loading
    if (this.isLoading) {
      this.pageLoadingOpen()
    }

    // 计算状态栏高度
    try {
      const system = uni.getSystemInfoSync()
      if (system.model) {
        this.statusBarHeight = system.statusBarHeight
      }
      // #ifdef APP-PLUS
      if (plus.navigator.isFullscreen()) {
        this.statusBarHeight = 0
      }
      // #endif
    } catch (e) {
      return null
    }

    // 获取自定义底部高度
    if (this.customFooter) {
      setTimeout(() => {
        this.getDomSize(
          'guiPageFooter',
          (res) => {
            this.footerHeight = res.height
          },
          0
        )
      }, 200)
    }

    // 获取自定义头部高度
    if (this.customHeader) {
      setTimeout(() => {
        this.getDomSize(
          'guiPageHeader',
          (res) => {
            this.headerHeight = res.height
            this.$nextTick(() => {
              this.pageStatus = true
            })
          },
          0
        )
      }, 200)
    } else {
      this.pageStatus = true
    }

    // 吸顶 top
    // #ifdef H5
    if (this.customHeader) {
      setTimeout(() => {
        this.getDomSize(
          'guiPageHeader',
          (res) => {
            this.fixedTop = res.height
          },
          0
        )
      }, 200)
    } else {
      this.fixedTop = 44
    }
    // #endif
    // #ifndef H5
    if (this.customHeader) {
      setTimeout(() => {
        this.getDomSize(
          'guiPageHeader',
          (res) => {
            this.fixedTop = res.height
          },
          0
        )
      }, 200)
    }
    // #endif

    // 全屏时适配吸顶插槽
    setTimeout(() => {
      this.getDomSize(
        'guiPageFixedTop',
        (res) => {
          this.fixedTopMargin = res.height
        },
        0
      )
    }, 200)
  },
  methods: {
    onpullingdown: function (e) {
      if (this.apiLoadingStatus) {
        return false
      }
      e.changedTouches = [{ pageY: e.pullingDistance }]
      this.$refs.guiPageRefresh.touchmove(e)
    },
    onrefresh: function () {
      if (this.apiLoadingStatus) {
        return false
      }
      this.refreshing = true
      this.$refs.guiPageRefresh.refreshStatus = 2
      setTimeout(() => {
        this.$refs.guiPageRefresh.rotate360()
      }, 200)
      this.$emit('reload')
    },
    pageLoadingOpen: function () {
      this.getRefs('guipageloading', 0, (ref) => {
        ref.open()
      })
    },
    pageLoadingClose: function () {
      this.getRefs('guipageloading', 0, (ref) => {
        ref.close()
      })
    },
    // 下拉刷新相关
    touchstart: function (e) {
      if (!this.refresh) {
        return false
      }
      if (this.apiLoadingStatus) {
        return false
      }
      this.$refs.guiPageRefresh.touchstart(e)
    },
    touchmove: function (e) {
      if (!this.refresh) {
        return false
      }
      if (this.apiLoadingStatus) {
        return false
      }
      this.$refs.guiPageRefresh.touchmove(e)
    },
    touchend: function (e) {
      if (!this.refresh) {
        return false
      }
      if (this.apiLoadingStatus) {
        return false
      }
      this.$refs.guiPageRefresh.touchend(e)
    },
    scroll: function (e) {
      if (this.srcollTimer != null) {
        clearTimeout(this.srcollTimer)
      }
      this.srcollTimer = setTimeout(() => {
        // #ifndef APP-NVUE
        this.$refs.guiPageRefresh.scroll(e)
        this.$emit('scroll', e)
        this.scrollTop = e.detail.scrollTop
        // #endif

        // #ifdef APP-NVUE
        e.detail = { scrollTop: e.contentOffset.y * -1 }
        this.$emit('scroll', e)
        this.scrollTop = e.detail.scrollTop
        // #endif
      }, 500)
    },
    toTop: function () {
      // #ifndef APP-NVUE
      this.topTagID = 'guiPageBodyTopTag'
      setTimeout(() => {
        this.topTagID = 'no'
      }, 500)
      // #endif
      // #ifdef APP-NVUE
      const el = this.$refs.guiPageBodyTopRef
      dom.scrollToElement(el, {})
      // #endif
    },
    endReload: function () {
      this.$refs.guiPageRefresh.endReload()
      this.refreshing = false
    },
    reload: function () {
      if (this.apiLoadingStatus) {
        return false
      }
      this.$emit('reload')
      if (this.loadmore) {
        this.$refs.guipageloadmore.stoploadmore()
      }
    },
    // 获取元素尺寸
    getDomSize: function (domIDOrRef, fun, count) {
      if (!count) {
        count = 1
      }
      if (count >= 50) {
        fun({ width: 0, height: 0 })
        return false
      }
      // #ifndef APP-NVUE
      uni
        .createSelectorQuery()
        .in(this)
        .select(`#${domIDOrRef}`)
        .boundingClientRect()
        .exec((res) => {
          if (res[0] == null) {
            count += 1
            setTimeout(() => {
              this.getDomSize(domIDOrRef, fun, count)
            }, 50)
            return
          } else {
            if (res[0].height == undefined) {
              count += 1
              setTimeout(() => {
                this.getDomSize(domIDOrRef, fun, count)
              }, 50)
              return
            }
            fun(res[0])
            return
          }
        })
      // #endif
      // #ifdef APP-NVUE
      const el = this.$refs[domIDOrRef]
      dom.getComponentRect(el, (res) => {
        if (res.result == false) {
          count += 1
          setTimeout(() => {
            this.getDomSize(domIDOrRef, fun, count)
          }, 50)
          return
        } else {
          if (res.size.height < 1) {
            count += 1
            setTimeout(() => {
              this.getDomSize(domIDOrRef, fun, count)
            }, 50)
            return
          }
          fun(res.size)
          return
        }
      })
      // #endif
    },
    stopfun: function (e) {
      e.stopPropagation()
      return null
    },
    headerTap: function () {
      this.headerTapNumber++
      if (this.headerTapNumber >= 2) {
        this.$emit('gotoTop')
        this.headerTapNumber = 0
      } else {
        setTimeout(() => {
          this.headerTapNumber = 0
        }, 1000)
      }
    },
    getRefs: function (ref, count, fun) {
      if (count >= 50) {
        fun(this.$refs[ref])
        return false
      }
      const refReturn = this.$refs[ref]
      if (refReturn) {
        fun(refReturn)
      } else {
        count++
        setTimeout(() => {
          this.getRefs(ref, count, fun)
        }, 100)
      }
    },
    loadmorefun: function () {
      if (!this.loadmore) {
        return false
      }
      if (this.apiLoadingStatus) {
        return false
      }
      // 获取加载组件状态看一下是否还能继续加载
      // 保证触底只执行一次加载
      if (this.loadMoreTimer != null) {
        clearTimeout(this.loadMoreTimer)
      }
      this.loadMoreTimer = setTimeout(() => {
        const status = this.$refs.guipageloadmore.loadMoreStatus
        if (status != 0) {
          return null
        }
        this.$refs.guipageloadmore.loading()
        this.$emit('loadmorefun')
      }, 80)
    },
    stopLoadmore: function () {
      this.$refs.guipageloadmore.stoploadmore()
    },
    stoploadmore: function () {
      this.$refs.guipageloadmore.stoploadmore()
    },
    nomore: function () {
      this.$refs.guipageloadmore.nomore()
    },
    empty: function () {
      this.$refs.guipageloadmore.empty()
    },
    toast: function (msg) {
      uni.showToast({
        title: msg,
        icon: 'none',
      })
    },
    resetFooterHeight: function () {
      if (this.customFooter) {
        setTimeout(() => {
          this.getDomSize(
            'guiPageFooter',
            (res) => {
              this.footerHeight = res.height
            },
            0
          )
        }, 500)
      }
    },
    isIphoneBottom: function () {
      const system = uni.getSystemInfoSync()
      if (system.model) {
        system.model = system.model.replace(' ', '')
        system.model = system.model.toLowerCase()
        let res1 = system.model.indexOf('iphonex')
        if (res1 > 5) {
          res1 = -1
        }
        let res2 = system.model.indexOf('iphone1')
        if (res2 > 5) {
          res2 = -1
        }
        if (res1 != -1 || res2 != -1) {
          return true
        }
      }
      return false
    },
  },
}
</script>
<style scoped></style>
